/*
 * FLASH.c
 *
 *  Created on: June 28, 2022
 *      Author: Administrator
 */
#include "HAL.h"
#include "OLEDFONT.h"

u8 OLED_GRAM[128][4];

//更新显存到LCD
void OLED_Refresh_Gram(void) {
    u8 i, n;
    for (i = 0; i < 4; i++) {
        OLED_WR_Byte(0xb0 + i, OLED_CMD);    //设置页地址（0~7）
        OLED_WR_Byte(0x00, OLED_CMD);      //设置显示位置—列低地址
        OLED_WR_Byte(0x10, OLED_CMD);      //设置显示位置—列高地址
        for (n = 0; n < 128; n++) {
            OLED_WR_Byte(OLED_GRAM[n][i], OLED_DATA);
        }
    }
}

//向SSD1306写入一个字节。
//dat:要写入的数据/命令
//cmd:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat, u8 cmd) {
    if (cmd) {
        GPIOA_SetBits(OLED_DC_PIN);
    } else {
        GPIOA_ResetBits(OLED_DC_PIN);
    }
    SPI0_MasterSendByte(dat);
}


void OLED_Set_Pos(unsigned char x, unsigned char y)
{   OLED_WR_Byte(0xb0+y,OLED_CMD);
    OLED_WR_Byte(((x&0xf0)>>4)|0x10,OLED_CMD);
    OLED_WR_Byte((x&0x0f),OLED_CMD);
}

//开启OLED显示
void OLED_Display_On(void) {
    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X14, OLED_CMD);  //DCDC ON
    OLED_WR_Byte(0XAF, OLED_CMD);  //DISPLAY ON
}
//关闭OLED显示
void OLED_Display_Off(void) {
    OLED_WR_Byte(0X8D, OLED_CMD);  //SET DCDC命令
    OLED_WR_Byte(0X10, OLED_CMD);  //DCDC OFF
    OLED_WR_Byte(0XAE, OLED_CMD);  //DISPLAY OFF
}
//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!!
void OLED_Clear(void) {
    u8 i, n;
    for (i = 0; i < 4; i++)
        for (n = 0; n < 128; n++)
            OLED_GRAM[n][i] = 0X00;
    OLED_Refresh_Gram();  //更新显示
}

void OLED_Clear_Ram(void) {
    u8 i, n;
    for (i = 0; i < 4; i++)
        for (n = 0; n < 128; n++)
            OLED_GRAM[n][i] = 0X00;
}
//画点
//x:0~127
//y:0~63
//t:1 填充 0,清空
void OLED_DrawPoint(u8 x, u8 y, u8 t) {
    u8 i, m, n;
    i = y / 8;
    m = y % 8;
    n = 1 << m;
    if (t)
        OLED_GRAM[x][i] |= n;
    else
        OLED_GRAM[x][i] &= ~n;
}
//x1,y1,x2,y2 填充区域的对角坐标
//确保x1<=x2;y1<=y2 0<=x1<=127 0<=y1<=63
//dot:0,清空;1,填充
void OLED_Fill(u8 x1, u8 y1, u8 x2, u8 y2, u8 dot) {
    u8 x, y;
    for (x = x1; x <= x2; x++) {
        for (y = y1; y <= y2; y++)
            OLED_DrawPoint(x, y, dot);
    }
    OLED_Refresh_Gram();  //更新显示
}
//在指定位置显示一个字符,包括部分字符
//x:0~127
//y:0~63
//mode:0,反白显示;1,正常显示
//size:选择字体 12/16/24
void OLED_ShowChar(u8 x, u8 y, u8 chr, u8 size, u8 mode) {
    u8 temp, t, t1;
    u8 y0 = y;
    u8 csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); //得到字体一个字符对应点阵集所占的字节数
    chr = chr - ' ';        //得到偏移后的值
    for (t = 0; t < csize; t++) {
        if (size == 12)
            temp = asc2_1206[chr][t];       //调用1206字体
        else if (size == 16)
            temp = asc2_1608[chr][t];   //调用1608字体
        else if (size == 24)
            temp = asc2_2412[chr][t];   //调用2412字体
        else
            return;                             //没有的字库
        for (t1 = 0; t1 < 8; t1++) {
            if (temp & 0x80)
                OLED_DrawPoint(x, y, mode);
            else
                OLED_DrawPoint(x, y, !mode);
            temp <<= 1;
            y++;
            if ((y - y0) == size) {
                y = y0;
                x++;
                break;
            }
        }
    }
}
//m^n函数
u32 mypow(u8 m, u8 n) {
    u32 result = 1;
    while(n--)result*=m;
    return result;
}
//显示2个数字
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//mode:模式   0,填充模式;1,叠加模式
//num:数值(0~4294967295);
void OLED_ShowNum(u8 x, u8 y, u32 num, u8 len, u8 size, u8 mode) {
    u8 t, temp;
    u8 enshow = 0;
    for (t = 0; t < len; t++) {
        temp = (num / mypow(10, len - t - 1)) % 10;
        if (enshow == 0 && t < (len - 1)) {
            if (temp == 0) {
                OLED_ShowChar(x + (size / 2) * t, y, ' ', size, mode);
                continue;
            } else
                enshow = 1;

        }
        OLED_ShowChar(x + (size / 2) * t, y, temp + '0', size, mode);
    }
}
//显示字符串
//x,y:起点坐标
//size:字体大小
//*p:字符串起始地址
void OLED_ShowString(u8 x, u8 y, const u8 *p, u8 size, u8 mode) {
    while((*p<='~')&&(*p>=' '))                         //判断是不是非法字符!
    {
        if(x>(128-(size/2))) {x=0;y+=size;}
        if(y>(64-size)) {y=x=0;OLED_Clear();}
        OLED_ShowChar(x,y,*p,size,mode);
        x+=size/2;
        p++;
    }
}

void OLED_ShowChinese(u8 x,u8 y,u8 index,u8 size, u8 mode)
{
    u8 m,temp;
    u8 x0=x,y0=y;
    u16 i,size3=(size/8+((size%8)?1:0))*size;  //得到字体一个字符对应点阵集所占的字节数
    for(i=0;i<size3;i++)
    {
        if(size==12)
        {
            temp=Chinese_GBK12[index][i];
        }
        if(size==16)
        {
            temp=Chinese_GBK16[index][i];
        }//调用16*16字体
        else if(size==24)
        {
            temp=Chinese_GBK24[index][i];
        }//调用24*24字体
        else if(size==32)
        {
            temp=Chinese_GBK32[index][i];
        }//调用32*32字体
        else return;
        for(m=0;m<8;m++)
        {
            if(temp&0x01)OLED_DrawPoint(x,y,mode);
            else OLED_DrawPoint(x,y,!mode);
            temp>>=1;
            y++;
        }
        x++;
        if((x-x0)==size)
        {x=x0;y0=y0+8;}
        y=y0;
    }
}

void OLED_ShowText(u8 x, u8 y, char *str, u8 size, u8 mode)
{
    unsigned char i,k,t,length;
	unsigned int Index = 0;
	length = strlen(str);//取字符串总长
	for(k=0; k<length;)	{
		if(((uint8_t)(*(str+k))) <= 127){//小于128是ASCII符号
			OLED_ShowChar(x, y, *(str+k), size, mode);
			x += 8;//x坐标右移8
            k++;
		}else if(((uint8_t)(*(str+k))) > 127){
		    if(size < 12){
		        return;
		    }
            Index = ((uint8_t)(*(str+k)))<<16 | ((uint8_t)(*(str+k+1)))<<8 | ((uint8_t)(*(str+k+2)));
            for(i=0; i< sizeof(ChineseIndex)/sizeof(unsigned int); i++){
                if(Index == ChineseIndex[i]){
                    OLED_ShowChinese(x, y, i, size, mode);
                    x += size;
                    k += 3;
                    break;
                }
            }
        }
	}
}

//反显函数
void OLED_ColorTurn(u8 i)
{
  if(!i) OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
  else  OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
}

//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{
  if(i==0)
    {
      OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
      OLED_WR_Byte(0xA1,OLED_CMD);
    }
  if(i==1)
    {
      OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
      OLED_WR_Byte(0xA0,OLED_CMD);
    }
}

//初始化SSD1306
void OLED_Init(void) {
    GPIOA_SetBits(OLED_RES_PIN);
    DelayMs(100);
    GPIOA_ResetBits(OLED_RES_PIN);
    DelayMs(100);
    GPIOA_SetBits(OLED_RES_PIN);
    OLED_WR_Byte(0xAE, OLED_CMD); /*display off*/
    OLED_WR_Byte(0x00, OLED_CMD); /*set lower column address*/
    OLED_WR_Byte(0x10, OLED_CMD); /*set higher column address*/
    OLED_WR_Byte(0x00, OLED_CMD); /*set display start line*/
    OLED_WR_Byte(0xB0, OLED_CMD); /*set page address*/
    OLED_WR_Byte(0x81, OLED_CMD); /*contract control*/
    OLED_WR_Byte(0xFF, OLED_CMD); /*128*/
    OLED_WR_Byte(0xA6, OLED_CMD); /*normal / reverse*/
    OLED_WR_Byte(0xA8, OLED_CMD); /*multiplex ratio*/
    OLED_WR_Byte(0x1F, OLED_CMD); /*duty = 1/32*/
    OLED_WR_Byte(0xD3, OLED_CMD); /*set display offset*/
    OLED_WR_Byte(0x00, OLED_CMD);
    OLED_WR_Byte(0xD5, OLED_CMD); /*set osc division*/
    OLED_WR_Byte(0x80, OLED_CMD);
    OLED_WR_Byte(0xD9, OLED_CMD); /*set pre-charge period*/
    OLED_WR_Byte(0x1F, OLED_CMD);
    OLED_WR_Byte(0xDA, OLED_CMD); /*set COM pins*/
    OLED_WR_Byte(0x00, OLED_CMD);
    OLED_WR_Byte(0xDB, OLED_CMD); /*set vcomh*/
    OLED_WR_Byte(0x40, OLED_CMD);
    OLED_WR_Byte(0x8D, OLED_CMD); /*set charge pump enable*/
    OLED_WR_Byte(0x14, OLED_CMD);
    OLED_Clear();
    OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/
}
